package com.sunlands.qdcy.deskmate.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.support.RequestContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class RequestUtil {

    /*public static <T> T convertWith(HttpServletRequest req, Class<T> clazz, List<String> properties) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        T obj = clazz.newInstance();
        Map<String, String[]> propertiesMap = new HashMap<String, String[]>();
        for (String property : properties) {
            String beanName;
            String paramName;
            if (property.contains(":")) {
                String[] split = property.split(":", 2);
                beanName = split[0];
                paramName = split[1];
            } else {
                beanName = property;
                paramName = property;
            }
            propertiesMap.put(beanName, req.getParameterValues(paramName));
        }
        BeanUtils.populate(obj, propertiesMap);
        return obj;
    }*/


    /**
     * 获得一个字符串的长整型值
     *
     * @param longStr
     * @return
     */
    public static Long getLong(String longStr) {
        Long longval = null;
        try {
            longval = Long.parseLong(longStr);
        } catch (NumberFormatException nfe) {
            log.debug("error:" + nfe.getMessage());
        }
        return longval;
    }


    /**
     * 获得长整型的参数值
     *
     * @param request
     * @param paramName
     * @return
     */
    public static Long getLong(HttpServletRequest request, String paramName) {
        return getLong(request.getParameter(paramName));
    }


    /**
     * 获得一个字符串的字节型值
     *
     * @param byteStr
     * @return
     */
    public static byte getByte(String byteStr) {
        byte byteval = 0;
        try {
            byteval = Byte.parseByte(byteStr);
        } catch (NumberFormatException nfe) {
            log.warn("error:" + nfe.getMessage());
        }
        return byteval;
    }

    /**
     * 取客户端ip地址
     *
     * @param request
     * @return
     */
    public static String getRemoteAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (notFound(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (notFound(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (notFound(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 取客户端ip地址
     *
     * @param request
     * @return
     */
    public static String getNewRemoteAddr(HttpServletRequest request) {

        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if ("127.0.0.1".equals(ip)) {
                //根据网卡取本机配置的ip
                try {
                    InetAddress inet = InetAddress.getLocalHost();
                    ip = inet.getHostAddress();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        }
        //对于通过多个代理的情况，第一个IP为真实的IP，多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;


/*        String ip = request.getHeader("x-forwarded-for");
        if (notFound(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (notFound(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (notFound(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;*/
    }

    /**
     * 取客户端ip地址
     *
     * @param request
     * @return
     */
    public static String getRemoteAddr(HttpServletRequest request, String defaultParam) {
        String ip = null;
        if (notFound(ip)) {
            ip = request.getParameter(defaultParam);
        }
        if (notFound(ip)) {
            ip = getRemoteAddr(request);
        }
        return ip;
    }


    private static boolean notFound(String ip) {
        return ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip) || "0.0.0.0".equals(ip);
    }


    public static String getRequestParams(HttpServletRequest req, List<String> exceptParams) {
        StringBuilder strBuffer = new StringBuilder();
        Enumeration parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()) {

            if (strBuffer.length() > 0) {
                strBuffer.append("&");
            }

            String name = (String) parameterNames.nextElement();

            if (exceptParams.contains(name)) continue;

            String value = req.getParameter(name);

            strBuffer.append(name).append("=").append(value);
        }
        return strBuffer.toString();
    }


    public static Map<String, String> getRequestParamMap(HttpServletRequest req, List<String> exceptParams,String method) {
        return getRequestParamMap(req, exceptParams, false,method);
    }


    public static Map<String, String> getRequestParamMap(HttpServletRequest req, List<String> exceptParams, boolean filterEmpty) {
        Map<String, String> paramMap = new HashMap<String, String>();
        Enumeration parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String name = (String) parameterNames.nextElement();
            if (exceptParams.contains(name)) continue;
            String value = req.getParameter(name);
            if (filterEmpty && StringUtil.isEmpty(value)) {
                continue;
            }
            paramMap.put(name, value);
        }
        return paramMap;
    }

    public static Map<String, String> getRequestParamMap(HttpServletRequest req, List<String> exceptParams, boolean filterEmpty, String method) {
        Map<String, String> paramMap = new HashMap<String, String>();
        Enumeration parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String name = (String) parameterNames.nextElement();
            if (exceptParams.contains(name)) continue;
            String value = req.getParameter(name);
            /*if("GET".equals(method)){
                value = value.replaceAll(" ","+");
            }*/
            if (filterEmpty && StringUtil.isEmpty(value)) {
                continue;
            }
            paramMap.put(name, value);
        }
        return paramMap;
    }


    public static String toParam(Map<String, String> params, String encode) throws UnsupportedEncodingException {
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (stringBuilder.length() > 0) {
                stringBuilder.append("&");
            }
            if (encode == null) {
                stringBuilder.append(entry.getKey()).append("=").append(entry.getValue());
            } else {
                stringBuilder.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), encode));
            }

        }
        return stringBuilder.toString();
    }


  /*  public static Map parseQuery(HttpServletRequest req) throws ParseException {
        Map<String, String> requestParamMap = getRequestParamMap(req, Collections.<String>emptyList(), true);
        JSONObject query = new JSONObject();

        String q_native = req.getParameter("q_native");
        if (StringUtil.notEmpty(q_native)) {
            return JSONObject.parseObject(q_native);
        }


        for (Map.Entry<String, String> entry : requestParamMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();

            //q_n_eq_name=xxxx
            String[] split = key.split("_");
            if (split.length != 4 || !split[0].equalsIgnoreCase("q")) {
                continue;
            }

            query.put(split[3], filedLimit(split[2], getValue(split[1], value)));
        }
        return query;
    }
*/

    public static Map parseField(HttpServletRequest req) throws ParseException {
        String q_f = req.getParameter("q_f");
        if (StringUtil.notEmpty(q_f)) {
            String[] split = q_f.split(",");
            Map<String, Integer> field = new HashMap<String, Integer>();
            for (String s : split) {
                field.put(s, 1);
            }
            return field;
        } else {
            return null;
        }
    }


    static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");


    static public Object getValue(String typeKey, String value) throws ParseException {
        if (typeKey.equals("s")) {
            return value;
        }

        if (typeKey.equals("n")) {
            return Long.parseLong(value);
        }

        if (typeKey.equals("b")) {
            return Boolean.parseBoolean(value);
        }

        if (typeKey.equals("d")) {
            return dateFormat.parse(value).getTime();
        }

        throw new RuntimeException("type key [" + typeKey + "] not support");
    }


   /* public static Object filedLimit(String limitKey, Object value) throws ParseException {
        if (limitKey.equals("eq")) {
            return value;
        }

        if (limitKey.equals("ne")) {
            return MapUtil.getMap("$ne", value);
        }

        if (limitKey.equals("gt")) {
            return MapUtil.getMap("$gt", value);
        }

        if (limitKey.equals("gte")) {
            return MapUtil.getMap("$gte", value);
        }

        if (limitKey.equals("lt")) {
            return MapUtil.getMap("$lt", value);
        }

        if (limitKey.equals("lte")) {
            return MapUtil.getMap("$lte", value);
        }

        throw new RuntimeException("limit key [" + limitKey + "] not support");
    }
*/

    public static Map<String, String> parseParam(String param) {
        Map<String, String> paramMap = new HashMap<String, String>();
        String[] split = param.split("&");
        for (String s : split) {
            String[] kv = s.split("=");
            if (kv.length == 2) {
                paramMap.put(kv[0], kv[1]);
            }
        }
        return paramMap;
    }


    public static String getJSONPCallback(HttpServletRequest req) {
        String jsonp = req.getParameter("callback");
        if (StringUtil.notEmpty(jsonp)) {
            return jsonp;
        }
        return "callback";
    }


    public static String getRedirect(HttpServletRequest req) {
        String jsonp = req.getParameter("redirect");
        if (StringUtil.notEmpty(jsonp)) {
            return jsonp;
        }
        return null;
    }


    public static String getFmt(HttpServletRequest req) {
        String fmt = req.getParameter("fmt");
        if (StringUtil.notEmpty(fmt)) {
            return fmt;
        }
        return "json";
    }


    /**
     * 对参数map进行排序且utf-8编码
     *
     * @param @param  params2
     * @param @return
     * @param @throws UnsupportedEncodingException
     * @return String
     * @throws
     * @Title: concatParams
     * @Description: TODO
     */
    public static String concatParams(Map<String, String> params2) throws UnsupportedEncodingException {
        Object[] key_arr = params2.keySet().toArray();
        Arrays.sort(key_arr);
        String str = "";

        for (Object key : key_arr) {
            String val = params2.get(key);
            key = URLEncoder.encode(key.toString(), "UTF-8");
            val = URLEncoder.encode(val, "UTF-8");
            str += "&" + key + "=" + val;
        }

        return str.replaceFirst("&", "");
    }

    public static String concatNoEmptyParams(Map<String, Object> params2) throws UnsupportedEncodingException {
        Object[] key_arr = params2.keySet().toArray();
        Arrays.sort(key_arr);
        String str = "";

        for (Object key : key_arr) {
            String val = params2.get(key).toString();
            if(StringUtils.isNotEmpty(val)){
//                key = URLEncoder.encode(key.toString(), "UTF-8");
//                val = URLEncoder.encode(val, "UTF-8");
                str += "&" + key + "=" + val;
            }

        }

        return str.replaceFirst("&", "");
    }

    public static String concatNoEmptyParamsUnEncode(Map<String, Object> params2)  {
        Object[] key_arr = params2.keySet().toArray();
        Arrays.sort(key_arr);
        String str = "";

        for (Object key : key_arr) {
            if(Objects.isNull(params2.get(key))){
                continue;
            }
            String val = params2.get(key).toString();
            if(StringUtils.isNotEmpty(val)){
//                key = URLEncoder.encode(key.toString(), "UTF-8");
//                val = URLEncoder.encode(val, "UTF-8");
                str += "&" + key + "=" + val;
            }

        }

        return str.replaceFirst("&", "");
    }


    public static String concatParams(JSONObject jsonObject) throws UnsupportedEncodingException {
        Object[] key_arr = jsonObject.keySet().toArray();
        Arrays.sort(key_arr);
        String str = "";

        for (Object key : key_arr) {
            String val = jsonObject.getString(key.toString());
//            key = URLEncoder.encode(key.toString(), "UTF-8");
//            val = URLEncoder.encode(val, "UTF-8");
            str += "&" + key + "=" + val;
        }

        return str.replaceFirst("&", "");
    }

    public static String concatNoEmptyParams(JSONObject jsonObject) throws UnsupportedEncodingException {
        Object[] key_arr = jsonObject.keySet().toArray();
        Arrays.sort(key_arr);
        String str = "";

        for (Object key : key_arr) {
            String val = jsonObject.getString(key.toString());
            if(!StringUtils.isEmpty(val)){
                str += "&" + key + "=" + val;
            }
//            key = URLEncoder.encode(key.toString(), "UTF-8");
//            val = URLEncoder.encode(val, "UTF-8");

        }

        return str.replaceFirst("&", "");
    }

    /**
     * 转化成16进制码
     *
     * @param @param  b
     * @param @return
     * @return String
     * @throws
     * @Title: byte2hex
     * @Description: TODO
     */
    private static String byte2hex(byte[] b) {
        StringBuffer buf = new StringBuffer();
        int i;

        for (int offset = 0; offset < b.length; offset++) {
            i = b[offset];
            if (i < 0)
                i += 256;
            if (i < 16)
                buf.append("0");
            buf.append(Integer.toHexString(i));
        }

        return buf.toString();
    }

    /**
     * 生成sig方法
     *
     * @param @param  params
     * @param @param  consumerSecret
     * @param @return
     * @param @throws Exception
     * @return String
     * @throws
     * @Title: genSig
     * @Description: TODO
     */
    public static String genSig(Map<String, String> params,
                                String consumerSecret) throws Exception {
        String str = concatParams(params);
        str = str + consumerSecret;
        MessageDigest md = MessageDigest.getInstance("SHA1");
        return byte2hex(md.digest(byte2hex(str.getBytes("UTF-8")).getBytes()));
    }

    /**
     * 去空参数的生成md5字符串
     * @param params
     * @return
     * @throws Exception
     */
    public static String getMd5ForSig(Map<String, Object> params) throws Exception {
        String str = concatNoEmptyParams(params);
        return MD5Util.MD5(str);
    }

    /**
     * 去空参数的生成md5字符串
     * @param params
     * @return
     * @throws Exception
     */
    public static String getMd5ForSig(Map<String, Object> params,String secretekey,String secretevalue)  {
        String str = concatNoEmptyParamsUnEncode(params);
        str += "&"+secretekey+"="+secretevalue;
        return MD5.MD5Encode(str).toUpperCase();
//        return MD5Util.md5(str,true,null);
    }

    /**
     * 验证header参数是否有效
     *
     * @param @param  req
     * @param @return
     * @return String
     * @throws
     * @Title: checkheader
     * @Description: TODO
     */
    public static String checkheaderparam(HttpServletRequest req) throws Exception {
        String api_key = req.getHeader("api_key");
        String sig = req.getHeader("sig");
        String timestamp = req.getHeader("timestamp");

        if (StringUtil.isEmpty(api_key)) {
            return "缺少参数api_key";
        } else if (StringUtil.isEmpty(sig)) {
            return "缺少参数sig";
        } else if (StringUtil.isEmpty(timestamp)) {
            return "缺少参数timestamp";
        } else {
            return "";
        }
    }

    public static String checkverify(HttpServletRequest req) throws Exception {
        String api_key = req.getHeader("api_key");
        String sig = req.getHeader("sig");
        String timestamp = req.getHeader("timestamp");

        if (StringUtil.isEmpty(api_key)) {
            return "缺少参数api_key";
        } else if (StringUtil.isEmpty(sig)) {
            return "缺少参数sig";
        } else if (StringUtil.isEmpty(timestamp)) {
            return "缺少参数timestamp";
        } else {
            return "";
        }
    }

    public static Map<String, String> getParametersSetPostMap(HttpServletRequest request, String... args) {


        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < args.length; i++) {
            map.put(args[i], request.getParameter(args[i]));
        }


        return map;
    }

    public static Map<String, String> getParametersSetPostMap(HttpServletRequest request, Map<String, String> defaultValueMap, String... args) {


        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < args.length; i++) {
            if (StringUtils.isEmpty(request.getParameter(args[i]))) {
                if (defaultValueMap.get(args[i]) != null) {
                    map.put(args[i], defaultValueMap.get(args[i]));
                } else {
                    //非默认值 参数为空
                }
            } else {
                map.put(args[i], request.getParameter(args[i]));
            }
        }

        return map;
    }

    /**
     * @param request
     * @param conditionMap key 为参数名,value 为* 时指参数为必填参数，value 为其他值时指当期参数的默认值
     * @return post所需的参数map
     * @throws Exception 必填参数值为空时抛出
     */
    public static Map<String, String> getParametersSetPostMap(HttpServletRequest request, Map<String, String> conditionMap) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        String method = request.getMethod();
        Map<String, String[]> parammap = request.getParameterMap();
        Map<String, String> paramlistmap = getRequestParamMap(request, new ArrayList<String>(),method);
        boolean flag = false;

        if(StringUtil.isEmpty(request.getParameter("isUseCache"))){
            flag = true;
        }else{
            flag = false;
        }
        if (flag) {
            String resig = request.getHeader("sig");
            if(!StringUtil.isEmpty(resig)){
                String sig = ElemeHelper.getSig(paramlistmap);

                if (!sig.equals(resig)) {
                    //错误 必填参数为空
                    throw new IllegalArgumentException("sig不正确非法请求");
                }
            }

        }
        for (String key : parammap.keySet()) {
            if (!conditionMap.containsKey(key)) {
                conditionMap.put(key, "");
            }
        }


        for (Map.Entry<String, String> entry : conditionMap.entrySet()) {
            String value = request.getParameter(entry.getKey());
            if (StringUtil.isEmpty(value)) {
                if (!"*".equals(entry.getValue())) {
                    if (StringUtils.isNotEmpty(entry.getValue())) {
                        map.put(entry.getKey(), entry.getValue());
                    } else {
                        map.put(entry.getKey(), "");
                    }

                }
                else {
                    //错误 必填参数为空
                    throw new IllegalArgumentException("错误:" + entry.getKey() + "为必填参数为空!");
                }
            } else {
                map.put(entry.getKey(), value);
            }
        }
        return map;
    }


    /**
     * @param request
     * @param conditionMap key 为参数名,value 为* 时指参数为必填参数，value 为其他值时指当期参数的默认值
     * @return post所需的参数map
     * @throws Exception 必填参数值为空时抛出
     */
    public static Map<String, String> getParametersSetPostMap(HttpServletRequest request, Map<String, String> conditionMap, boolean flag) throws Exception {
        request.setCharacterEncoding("utf-8");
        Map<String, String> map = new HashMap<String, String>();
        Map<String, String[]> parammap = request.getParameterMap();
        String method = request.getMethod();
        Map<String, String> paramlistmap = getRequestParamMap(request, new ArrayList<String>(),method);
        String apikey = "sunlandszlcx";
        if (flag) {
            paramlistmap.put("apiKey", apikey);
            String sig = ElemeHelper.getSig(paramlistmap);
            String resig = request.getHeader("sig");
            if (!sig.equals(resig)) {
                //错误 必填参数为空
                throw new Exception("sig不正确非法请求");
            }
        }
        for (String key : parammap.keySet()) {
            if (!conditionMap.containsKey(key)) {
                conditionMap.put(key, "");
            }
        }


        for (Map.Entry<String, String> entry : conditionMap.entrySet()) {
            String value = request.getParameter(entry.getKey());
            if (StringUtil.isEmpty(value)) {
                if (!"*".equals(entry.getValue())) {
                    if (StringUtils.isNotEmpty(entry.getValue())) {
                        map.put(entry.getKey(), entry.getValue());
                    } else {
                        map.put(entry.getKey(), "");
                    }

                } else {
                    //错误 必填参数为空
                    throw new Exception("错误:" + entry.getKey() + "为必填参数为空!");
                }
            } else {
                map.put(entry.getKey(), value);
            }
        }
        return map;
    }

    public static Map<String, String> replaceParam(Map<String, String> param, String oldParam, String newParam) {

        param.put(newParam, param.get(oldParam));
        param.remove(oldParam);

        return param;

    }

    public static void changeTanentId(Map<String, String> paramap) {
        boolean flag = false;
        if (flag) {
            String tenantId = paramap.get("tenantId");
            if (!StringUtils.isEmpty(tenantId)) {
                if ("818537".equals(tenantId)) {
                    paramap.put("tenantId", "148893");
                }
            }
        }
    }

    public static String getLocalUrl(HttpServletRequest request) {
        return request.getLocalAddr();
    }

    public static String getLocalUrl() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return "";
        }
    }

    public static RequestContext getNationalContext(HttpServletRequest request, HttpServletResponse response) {
        RequestContext requestContext = null;

        try {
//            String langType = request.getParameter("language");
            String langType = "zh";

            if (langType == null) {
                (new CookieLocaleResolver()).setLocale(request, response, LocaleContextHolder.getLocale());
            } else {
                if (langType.equals("zh")) {
                    Locale locale = new Locale("zh", "CN");
                    //request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME,locale);
                    (new CookieLocaleResolver()).setLocale(request, response, locale);
                } else if (langType.equals("en")) {
                    Locale locale = new Locale("en", "US");
                    //request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME,locale);
                    (new CookieLocaleResolver()).setLocale(request, response, locale);
                } else {
                    (new CookieLocaleResolver()).setLocale(request, response, LocaleContextHolder.getLocale());
                }
            }
            requestContext = new RequestContext(request);

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            return requestContext;
        }
    }

}

